package com.example.flower_shop.filter;

import com.example.flower_shop.service.JwtService;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class);

    @Autowired
    private JwtService jwtService;

    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    private final List<String> permitAllPaths = Arrays.asList(
            "/api/users/register",
            "/api/users/login",
            "/api/test/public",
            "/api/categories/**",
            "/api/products/**",
            "/uploads/**",
            "/swagger-ui/**",
            "/swagger-resources/**",
            "/v2/api-docs",
            "/v3/api-docs",
            "/webjars/**",
            "/swagger-ui.html");

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        String path = request.getServletPath();
        String method = request.getMethod();

        logger.info("正在处理请求: {} {}", method, path);

        // 评论相关的请求处理
        if (path.startsWith("/api/reviews/")) {
            // 只允许GET请求跳过过滤器
            if ("GET".equals(method)) {
                logger.info("允许GET方法访问评论: {} {}", method, path);
                return true;
            }
            // 其他方法（POST、PUT、DELETE）需要认证
            logger.info("评论请求需要认证: {} {}", method, path);
            return false;
        }

        // 处理其他公开路径
        boolean shouldNotFilter = permitAllPaths.stream()
                .anyMatch(pattern -> pathMatcher.match(pattern, path));

        logger.info("请求路径: {}", path);
        logger.info("是否跳过过滤: {}", shouldNotFilter);

        if (shouldNotFilter) {
            String matchedPattern = permitAllPaths.stream()
                    .filter(pattern -> pathMatcher.match(pattern, path))
                    .findFirst()
                    .orElse("无");
            logger.info("匹配的公开路径模式: {}", matchedPattern);
        } else {
            logger.info("需要认证的请求");
        }

        return shouldNotFilter;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        try {
            String token = getJwtFromRequest(request);
            String path = request.getServletPath();
            String method = request.getMethod();

            logger.info("处理请求: {} {} Token: {}", method, path, token != null ? "存在" : "不存在");

            if (StringUtils.hasText(token)) {
                try {
                    boolean isValid = jwtService.validateToken(token);
                    logger.info("Token 验证结果: {}", isValid ? "有效" : "无效");

                    if (isValid) {
                        Authentication authentication = jwtService.getAuthentication(token);
                        if (authentication != null && authentication.isAuthenticated()) {
                            SecurityContextHolder.getContext().setAuthentication(authentication);
                            logger.info("已设置认证信息: 用户ID={}, 权限={}, 路径={}",
                                    authentication.getPrincipal(),
                                    authentication.getAuthorities(),
                                    path);
                        } else {
                            logger.warn("认证对象无效: {}", path);
                            handleAuthenticationError(response, "Invalid authentication",
                                    HttpServletResponse.SC_UNAUTHORIZED);
                            return;
                        }
                    } else {
                        logger.warn("Token 无效: {}", path);
                        handleAuthenticationError(response, "Invalid token", HttpServletResponse.SC_UNAUTHORIZED);
                        return;
                    }
                } catch (ExpiredJwtException e) {
                    logger.warn("Token 已过期: {} - {}", path, e.getMessage());
                    handleAuthenticationError(response, "Token has expired", HttpServletResponse.SC_UNAUTHORIZED);
                    return;
                } catch (JwtException e) {
                    logger.error("JWT 验证错误: {} - {}", path, e.getMessage());
                    handleAuthenticationError(response, "Invalid token", HttpServletResponse.SC_UNAUTHORIZED);
                    return;
                } catch (BadCredentialsException e) {
                    logger.error("无效的凭证: {} - {}", path, e.getMessage());
                    handleAuthenticationError(response, "Invalid credentials", HttpServletResponse.SC_UNAUTHORIZED);
                    return;
                }
            } else if (!shouldNotFilter(request)) {
                logger.warn("需要认证但未提供Token: {}", path);
                handleAuthenticationError(response, "Authentication required", HttpServletResponse.SC_UNAUTHORIZED);
                return;
            }

            filterChain.doFilter(request, response);
        } catch (Exception e) {
            logger.error("JWT 认证过程发生错误: {}", e.getMessage(), e);
            handleAuthenticationError(response, "Internal server error", HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    private String getJwtFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        logger.info("Authorization 请求头: {}", bearerToken != null ? "存在" : "不存在");

        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            String token = bearerToken.substring(7);
            logger.info("成功提取 Token");
            return token;
        }
        logger.info("Authorization 请求头格式不正确或为空");
        return null;
    }

    private void handleAuthenticationError(HttpServletResponse response, String message, int status)
            throws IOException {
        SecurityContextHolder.clearContext();
        response.setStatus(status);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write(String.format("{\"message\":\"%s\"}", message));
    }
}